#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>
#define MAXSIZE 128
#define MAXARGS 32
//故意设计成全局的

const char* psep=" ";
//命令行参数表
char *gargv[MAXARGS];
int gargc=0;
//我们shell自己的工作路径
char cwd[MAXSIZE];
//环境变量参数表
int genvc=0;
char *genv[MAXARGS];
int lastcode=0;

void Loadenv()
{
	//正常情况下从配置文件拷贝
	//今天我们从父进程拷贝
	extern char **environ;
	
	for(;environ[genvc];genvc++)
	{
		genv[genvc]=new char[1024];
		strcpy(genv[genvc],environ[genvc]);
	}
	genv[genvc]=NULL;
}
const char* GetUserName()
{
	char *name=getenv("USER");
	if(name==NULL)
		return "None";
	return name;
}
const char* GetHostName()
{
	const char* hostname=getenv("HOSTNAME");
	if(hostname==NULL)
		return "None";
	return hostname;
} 
const char* GetPWD()
{
	const char* pwd=getenv("PWD");
	//char* pwd=getcwd(cwd,sizeof(cwd));
	if(pwd==NULL)
	{
		return "None";
	}
	return pwd;
}
static std::string rFindDir(const std::string &p)
{
	if(p=="/")
		return p;
	const std::string psep="/";
	auto pos=p.rfind(psep);
	if(pos==std::string::npos)
	return std::string();
	return p.substr(pos+1);

}


void PrintCommandLine()
{
	printf("[%s@%s %s]#",GetUserName(),GetHostName(),rFindDir(GetPWD()).c_str());//用户名@主机名 当前路径
	fflush(stdout);	
}




 int GetCommandLine(char command_line[],int size)
{
	if(fgets(command_line,size,stdin)==NULL)
		return 0;
	//用户在输入的时候至少输一次\n
	command_line[strlen(command_line)-1]='\0';
	return strlen(command_line);
}




int ParseCommand(char command_line[])
{
	//首先置零
	gargc=0;
	memset(gargv,0,sizeof(gargv));
	gargv[0]=strtok(command_line,psep);
	while(gargv[++gargc]=strtok(NULL,psep));
//	printf("gargc=%d\n",gargc);
//	int i=0;
//	for(;gargv[i];i++)
//	{
//		printf("gargv[%d]=%s\n",i,gargv[i]);
//	}
	return gargc;
}


//return val
//0 不是内建命令
//1 内建命令执行完毕
int CheckBuildinExecute()
{
	if(!strcmp(gargv[0],"cd"))
	{
		if(gargc==2)
		{
			//改变程序工作路径
			//1.改变内核中的路径
			chdir(gargv[1]);
			//改变环境变量
			char pwd[1024];
			getcwd(pwd,sizeof(pwd));
			snprintf(cwd,sizeof(cwd),"PWD=%s",pwd);
			putenv(cwd);
			lastcode=0;
		}
			return 1;
	}
	if(!strcmp(gargv[0],"echo"))
	{
		if(gargv[1][0]=='$')
		{
			if(!strcmp(gargv[1]+1,"?"))
				printf("lastcode=%d\n",lastcode);
			lastcode=0;
			if(!strcmp(gargv[1]+1,"PATH"))
				printf("PATH=%s\n",getenv("PATH"));
		}
		return 1;
	}
	return 0;
}

int ExecuteCommand()
{
	pid_t id=fork();
	if(id<0)
	{
		return -1;
	}else if(id==0){
		execvpe(gargv[0],gargv,genv);
		perror(gargv[0]);
		exit(1);
	}else{
		//父进程
		int status=0;
		int rid=waitpid(id,&status,0);
		if(rid>0)
		{
//			printf("wait child process success!\n");
			lastcode=WEXITSTATUS(status);
		}
			return 0;
	}
}


int main()
{
	char command_line[MAXSIZE]={0};
	while(1)
	{
		//0.默认从配置文件中填充环境变量表
		Loadenv();
		//1.打印字符串
		PrintCommandLine();
		//sleep(10000);
		//2.获取用户输入
		if(!GetCommandLine(command_line,MAXSIZE))
			continue;
		//3.解析字符串，命令行解释器首先要对用户输入的字符串进行解析
		ParseCommand(command_line);
		//4.内建命令
		if(CheckBuildinExecute())
			continue;
		//5.子进程运行命令
		ExecuteCommand();
	}
	return 0;
}
